package com.fjec.market.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fjec.common.protocol.JsonResult;
import com.fjec.common.shiro.AccountInfo;
import com.fjec.common.util.JsonUtil;
import com.fjec.common.util.SpecialMapUtil;
import com.fjec.market.entity.InfoBusiness;
import com.fjec.market.entity.InfoFarmer;
import com.fjec.market.entity.InfoPurchase;
import com.fjec.market.entity.InfoSku;
import com.fjec.market.es.document.BusinessDocument;
import com.fjec.market.es.document.FarmerDocument;
import com.fjec.market.es.document.PurchaseDocument;
import com.fjec.market.es.document.SpuDocument;
import com.fjec.market.es.repository.BusinessRepository;
import com.fjec.market.es.repository.FarmerRepository;
import com.fjec.market.es.repository.PurchaseRepository;
import com.fjec.market.es.repository.SpuRepository;
import com.fjec.market.service.*;
import com.fjec.market.view.ShopVO;
import org.apache.commons.collections.MapUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional
public class SearchServiceImpl implements ISearchService {

    @Autowired
    private SpuRepository spuRepository;

    @Autowired
    private BusinessRepository businessRepository;

    @Autowired
    private FarmerRepository farmerRepository;

    @Autowired
    private PurchaseRepository purchaseRepository;

    @Autowired
    private IInfoSkuService infoSkuService;

    @Autowired
    private IInfoBusinessService infoBusinessService;

    @Autowired
    private IInfoFarmerService infoFarmerService;

    @Autowired
    private IInfoPurchaseService infoPurchaseService;

    @Resource
    private IInfoMarketService infoMarketService;

    /**
     * 商品和店铺的搜索接口
     * @param markCode 市场编码,无需限定市场时传0
     * @param target 搜索类型，1 = 商品，2 = 店铺
     * @param busiType 行业类型，2 = 果农，3 = 分拣厂， 4 = 农资物料厂， 5 = 包装厂， 6 = 采购商
     * @return
     */
    @Override
    @Cacheable(value = "c_3", key = "'fjec:search:' + #markCode + ':' + #target + ':' + #busiType + ':' + #title + ':' + #page.getCurrent() + '-' + #page.getSize()")
    public Map<String, Object> getSearchResult(int markCode, int target, int busiType, String title, Page page) {
        Long userId = 0L;
        if (SecurityUtils.getSubject().isAuthenticated())
            userId = AccountInfo.getUserId();

        Map<String, Object> m = new HashMap<>();
        if (target == 1) {
            List<SpuDocument> spuDocuments = spuRepository.findBySpuTitle(title);
            List<Long> spuIds = spuDocuments.stream().map(SpuDocument::getId).collect(Collectors.toList());
            if (spuIds.size() == 0) {
                m.put("data", new ArrayList<>());
                m.put("total", 0);
                return m;
            }
            List<Map<String, Object>> skus;
            // busiType=23 查询果农和分拣厂的水果
            if (busiType == 23) {
                skus = infoSkuService.getRetailFruits(markCode, spuIds, 1, 0, page);
            } else
                skus = infoSkuService.getSkusBySpuIDsAndMarkCodeAndBusiType(markCode, busiType, spuIds, 1, 0, page);
            List<Map<String, Object>> l = new ArrayList<>();
            skus.forEach(sku -> {
                String spuPics = MapUtils.getString(sku, "SpuPics");
                if (spuPics != null) sku.put("SpuPics", JsonUtil.jsonToObject(spuPics, List.class));
                String spuVideos = MapUtils.getString(sku, "SpuVideos");
                if (spuVideos != null) sku.put("SpuVideos", JsonUtil.jsonToObject(spuVideos, List.class));
                l.add(SpecialMapUtil.lowKey(sku));
            });
            m.put("data", l);
            m.put("total", page.getTotal());
        } else if (target == 2) {
            // 判断是否是店铺号
            String shopNumStr = title.replaceAll("-", "");
            boolean isShopNum = false;
            Long shopNum = 0L;
            try {
                shopNum = Long.parseLong(shopNumStr);
                isShopNum = true;
            } catch (NumberFormatException e) {

            }

            List<ShopVO> finalResult = new ArrayList<>();
            if (busiType == 2) {
                // find by shopNum
                if (isShopNum) {
                    List<InfoFarmer> farmerByNum = infoFarmerService.getFarmerByShopNumAndMarkCode(markCode, shopNum);
                    List<ShopVO> shopByNum = infoMarketService.extendFarmer(farmerByNum, userId, true);
                    finalResult.addAll(shopByNum);
                }
                // end
                List<FarmerDocument> farmerDocuments = farmerRepository.findByShopName(title);
                List<Long> farmerIds = farmerDocuments.stream().map(FarmerDocument::getId).collect(Collectors.toList());
                if (farmerIds.size() == 0) {
                    m.put("data", finalResult);
                    m.put("total", finalResult.size());
                    return m;
                }
                List<InfoFarmer> farmers = infoFarmerService.getFarmersByFarmerIdsAndMarkCode(markCode, farmerIds, page);
                finalResult.addAll(infoMarketService.extendFarmer(farmers, userId, true));
                m.put("data", finalResult);
                m.put("total", page.getTotal());
            } else if (busiType == 3 || busiType == 4 || busiType == 5) {
                // find by shopNum
                if (isShopNum) {
                    List<InfoBusiness> businessByNum = infoBusinessService.getBusinessByShopNumAndMarkCode(markCode, shopNum, busiType);
                    List<ShopVO> shopByNum = infoMarketService.extendBusiness(businessByNum, userId, true);
                    finalResult.addAll(shopByNum);
                }
                // end
                List<BusinessDocument> businessDocuments = businessRepository.findByShopNameAndBusiType(title, busiType);
                List<Long> businessIds = businessDocuments.stream().map(BusinessDocument::getId).collect(Collectors.toList());
                if (businessIds.size() == 0) {
                    m.put("data", finalResult);
                    m.put("total", finalResult.size());
                    return m;
                }
                List<InfoBusiness> businesses = infoBusinessService.getBusinessesByBusinessIdsAndMarkCode(markCode, businessIds, busiType, page);
                finalResult.addAll(infoMarketService.extendBusiness(businesses, userId, true));
                m.put("data", finalResult);
                m.put("total", page.getTotal());
            } else if (busiType == 6) {
                // find by shopNum
                if (isShopNum) {
                    List<InfoPurchase> purchaseByNum = infoPurchaseService.getPurchaseByShopNumAndMarkCode(markCode, shopNum);
                    List<ShopVO> shopByNum = infoMarketService.extendPurchase(purchaseByNum, userId, true);
                    finalResult.addAll(shopByNum);
                }
                // end
                List<PurchaseDocument> purchaseDocuments = purchaseRepository.findByShortName(title);
                List<Long> purchaseIds = purchaseDocuments.stream().map(PurchaseDocument::getId).collect(Collectors.toList());
                if (purchaseIds.size() == 0) {
                    m.put("data", finalResult);
                    m.put("total", finalResult.size());
                    return m;
                }
                List<InfoPurchase> purchases = infoPurchaseService.getPurchasesByPurchaseIdsAndMarkCode(markCode, purchaseIds, page);
                finalResult.addAll(infoMarketService.extendPurchase(purchases, userId, true));
                m.put("data", finalResult);
                m.put("total", page.getTotal());
            }
        }
        ObjectMapper objectMapper = new ObjectMapper();
        Map result = objectMapper.convertValue(m, Map.class);
        return result;
    }
}
